package com.zxy.supplier_system.server.controller

import com.zxy.supplier_system.server.controller.GoodsController.GoodsDetail.SubGoodsResponse
import com.zxy.supplier_system.server.entity.Authority
import com.zxy.supplier_system.server.entity.Procurement
import com.zxy.supplier_system.server.repository.QueryGoodsUnitResponse
import com.zxy.supplier_system.server.service.MarketOrderWithProcurementConvertService
import com.zxy.supplier_system.server.service.ProcurementService
import com.zxy.supplier_system.server.utils.IntIdAndName
import com.zxy.supplier_system.server.utils.LongIdAndName
import org.springframework.beans.factory.annotation.Value
import org.springframework.core.io.InputStreamResource
import org.springframework.core.io.Resource
import org.springframework.data.domain.Page
import org.springframework.data.domain.Pageable
import org.springframework.data.domain.Sort
import org.springframework.data.web.SortDefault
import org.springframework.web.bind.annotation.*
import java.math.BigDecimal
import java.time.LocalDate
import java.time.OffsetDateTime

@RestController
@RequestMapping("procurementSuppliers/orders")
class ProcurementController(
    private val procurementService: ProcurementService,
    @Value("classpath:excel/templates/导入采购货品模板.xlsx")
    private val importProcurementItemsTemplate: Resource,
    private val marketOrderWithProcurementConvertService: MarketOrderWithProcurementConvertService,
) {

    class QueryProcurementRequest(
        val supplierIds: List<Int> = emptyList(),
        val startDate: LocalDate?,
        val endDate: LocalDate?,
        val createdByIds: List<Int> = emptyList(),
        val status: Procurement.Status?,
    )

    @HasAuthority(Authority.采购_查询)
    @GetMapping
    fun queryProcurement(
        queryProcurementRequest: QueryProcurementRequest,
        @SortDefault("createdDateTime", direction = Sort.Direction.DESC) pageable: Pageable
    ): Page<QueryProcurementResponse> {
        return this.procurementService.queryProcurement(queryProcurementRequest, pageable)
    }

    data class QueryProcurementResponse(
        val id: Int,
        val createdBy: IntIdAndName,
        val createdDateTime: OffsetDateTime,
        val goodsKindAmount: Int,
        val supplier: IntIdAndName,
        val status: Procurement.Status,
        val receiptId: Int?,
        val note: String?,
        val totalFee: BigDecimal,
    )

    data class UpdateOrderGoodsRequest(
        val items: List<OrderGoodsItem>
    )

    data class OrderGoodsItem(
        val id: Int,
        val amount: Int
    )

    @HasAuthority(Authority.采购_修改)
    @PatchMapping("{id}/goods")
    fun updateOrderGoods(
        @RequestBody updateOrderGoodsRequest: UpdateOrderGoodsRequest, @PathVariable id: Int,
    ) {
        return this.procurementService.updateOrderGoods(id, updateOrderGoodsRequest)
    }

    @HasAuthority(Authority.采购_下单)
    @GetMapping("{id}")
    fun getProcurementDetail(@PathVariable id: Int, includeItems: Boolean = false): ProcurementDetail {
        return this.procurementService.getProcurementDetail(id, includeItems)
    }

    data class ProcurementDetail(
        val id: Int,
        val createdDateTime: OffsetDateTime,
        val createdBy: IntIdAndName,
        val supplier: IntIdAndName,
        val items: List<ProcurementItemResponse>,
        val submittedDateTime: OffsetDateTime?,
        val receiptDateTime: OffsetDateTime?,
        val receiptId: Int?,
        val note: String?
    )

    data class ProcurementItemResponse(
        val id: Int,
        val name: String,
        val barcode: String,
        val price: BigDecimal,
        val amount: Int,
        val createdDateTime: OffsetDateTime,
        val lastModifiedDateTime: OffsetDateTime?,
        val brand: IntIdAndName?,
        val category: IntIdAndName?,
        val factory: IntIdAndName?,
        val amountInOrder: Int,
        val boxSpecification: String?,
        val unit: LongIdAndName?,
        val units: List<QueryGoodsUnitResponse>,
        val subGoods: SubGoodsResponse? = null,
        val note: String? = null,
        val purchasePrice: BigDecimal,
    )

    @HasAuthority(Authority.采购_查询)
    @GetMapping("employees", params = ["projection=summary"])
    fun getProcurementCreatedEmployees(): List<IntIdAndName> {
        return this.procurementService.getAllEmployees()
    }


    @HasAuthority(Authority.采购_下单)
    @PatchMapping("{id}/submit")
    fun submitOrder(@PathVariable id: Int) {
        return this.procurementService.submitProcurement(id)
    }

    @HasAuthority(Authority.采购_入库_入库)
    @PostMapping("{id}/receipt")
    fun receipt(@PathVariable id: Int): Int {
        return this.procurementService.receipt(id).id
    }

    @HasAuthority(Authority.采购_修改)
    @GetMapping("items/excel/import/template")
    fun downloadImportTemplate(): InputStreamResource {
        return InputStreamResource(importProcurementItemsTemplate.inputStream)
    }

    data class UpdateProcurementNoteRequest(
        val note: String,
    )

    @HasAuthority(Authority.采购_修改)
    @PatchMapping("{id}/note")
    fun updateProcurementNote(@PathVariable id: Int, @RequestBody request: UpdateProcurementNoteRequest) {
        this.procurementService.updateProcurementNote(id, request)
    }

    @HasAuthority(Authority.采购_删除)
    @DeleteMapping("{id}")
    fun delete(@PathVariable id: Int) {
        return this.procurementService.delete(id)
    }

    @PostMapping("{procurementId}/convertToMarket")
    fun convertToMarket(marketId: Int, @PathVariable procurementId: Int): Int {
        return marketOrderWithProcurementConvertService.convertToMarketOrder(procurementId, marketId).id
    }

}
